package com.xmhmyh.generalframework.common.utils;

import com.xmhmyh.generalframework.common.SFunction;
import com.xmhmyh.generalframework.common.enums.YesOrNo;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.io.Serializable;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author: 于丁
 * @DateTime: 2019/12/30 6:58 下午
 */
public class MyBeanUtils {

    private static Map<Class, SerializedLambda> CLASS_LAMDBA_CACHE = new ConcurrentHashMap<>();


    /**
     * @Author: 于丁
     * @Description: object 转换成 map
     * @DateTime: 2020/1/16 5:31 下午
     * @Params:
     * @Return
     */
    public static Map<String, Object> object2map(Object t) throws IllegalAccessException {
        Map<String, Object> map = new HashMap<>();
        Field[] fields = t.getClass().getDeclaredFields();
        for (Field field : fields) {
            boolean flag = field.isAccessible();
            field.setAccessible(true);
            Object o = field.get(t);
            if (o != null) {
                map.put(field.getName(), o);
            }
        }
        return map;
    }

    /***
     * 转换方法引用为属性名
     * ::getField 转换 属性名
     * @param fn
     * @return
     */
    public static <T> String convertToFieldName(SFunction<T> fn) {
        SerializedLambda lambda = getSerializedLambda(fn);
        // 获取方法名
        String methodName = lambda.getImplMethodName();
        String prefix = null;
        if (methodName.startsWith("get")) {
            prefix = "get";
        } else if (methodName.startsWith("is")) {
            prefix = "is";
        }
        if (prefix == null) {
            System.out.println("无效的getter方法: " + methodName);
        }
        // 截取get/is之后的字符串并转换首字母为小写
        return toLowerCaseFirstOne(methodName.replace(prefix, ""));

    }

    public static <T> T setSysInfo(T t, Long userId, Long accountId) {
        try {
            Class c = t.getClass();
            // 设置创建时间
            PropertyDescriptor propertyDescriptor = new PropertyDescriptor("createTime", c);
            propertyDescriptor.getWriteMethod().invoke(t, LocalDateTime.now());
            // 设置更新时间
            propertyDescriptor = new PropertyDescriptor("updateTime", c);
            propertyDescriptor.getWriteMethod().invoke(t, LocalDateTime.now());
            // 设置删除标识
            propertyDescriptor = new PropertyDescriptor("enabled", c);
            propertyDescriptor.getWriteMethod().invoke(t, YesOrNo.YES.getValue());
            if (userId != null) {
                // 设置创建人
                propertyDescriptor = new PropertyDescriptor("createBy", c);
                propertyDescriptor.getWriteMethod().invoke(t, userId);
                // 设置更新人
                propertyDescriptor = new PropertyDescriptor("updateBy", c);
                propertyDescriptor.getWriteMethod().invoke(t, userId);
            }
            if (accountId != null) {
                // 设置账户ID
                propertyDescriptor = new PropertyDescriptor("accountId", c);
                propertyDescriptor.getWriteMethod().invoke(t, accountId);

            }
            return t;
        } catch (IllegalAccessException | IntrospectionException | InvocationTargetException e) {
            e.printStackTrace();
            return t;
        }
    }

    public static <T> T updateSysInfo(T t, Long updatedBy) {
        try {
            Class c = t.getClass();
            // 设置更新时间
            PropertyDescriptor propertyDescriptor = new PropertyDescriptor("updateTime", c);
            propertyDescriptor.getWriteMethod().invoke(t, LocalDateTime.now());
            if (updatedBy != null) {
                // 设置更新人
                propertyDescriptor = new PropertyDescriptor("updateBy", c);
                propertyDescriptor.getWriteMethod().invoke(t, updatedBy);
            }
            return t;
        } catch (IllegalAccessException | IntrospectionException | InvocationTargetException e) {
            e.printStackTrace();
            return t;
        }
    }

    static String toLowerCaseFirstOne(String s) {
        if (Character.isLowerCase(s.charAt(0))) {
            return s;
        } else {
            return Character.toLowerCase(s.charAt(0)) + s.substring(1);
        }
    }

    /**
     * 关键在于这个方法
     */
    static SerializedLambda getSerializedLambda(Serializable fn) {
        SerializedLambda lambda = CLASS_LAMDBA_CACHE.get(fn.getClass());
        // 先检查缓存中是否已存在
        if (lambda == null) {
            try {
                // 提取SerializedLambda并缓存
                Method method = fn.getClass().getDeclaredMethod("writeReplace");
                method.setAccessible(Boolean.TRUE);
                lambda = (SerializedLambda) method.invoke(fn);
                CLASS_LAMDBA_CACHE.put(fn.getClass(), lambda);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return lambda;
    }

}
